﻿using System;
using System.Text;
using System.Windows;

using MQTTnet;
using MQTTnet.Client.Options;
using MQTTnet.Extensions.ManagedClient;

namespace MQTT.Demo.Client
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private IManagedMqttClient mqttClient;

        public MainWindow()
        {
            InitializeComponent();

            // 初始化Client
            mqttClient = new MqttFactory().CreateManagedMqttClient();

            //
            mqttClient.UseDisconnectedHandler(ee =>
            {
                WriteLog(">>> 服务器断开连接");
            });
            mqttClient.UseApplicationMessageReceivedHandler(ee =>
            {
                WriteLog(">>> 收到消息");
                WriteLog($"+ Topic = {ee.ApplicationMessage.Topic}");
                try
                {
                    WriteLog($"+ Payload = {Encoding.UTF8.GetString(ee.ApplicationMessage.Payload)}");
                }
                catch { }
                WriteLog($"+ QoS = {ee.ApplicationMessage.QualityOfServiceLevel}");
                WriteLog($"+ Retain = {ee.ApplicationMessage.Retain}");
                WriteLog("");
            });

            mqttClient.UseConnectedHandler(ee =>
            {
                WriteLog(">>> 连接到服务");
            });
        }

        public void WriteLog(string message)
        {
            if (!(txtRich.CheckAccess()))
            {
                this.Dispatcher.Invoke(() => WriteLog(message));
                return;
            }
            string strTime = "[" + System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] ";
            txtRich.AppendText(strTime + message + "\r");

        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            // 向服务端开放的端口进行服务请求
            var mqttClientOptions = new MqttClientOptionsBuilder()
                             .WithClientId(this.tbClientId.Text)// 传入ClientID参数
                             .WithTcpServer(this.tbHostAddr.Text, int.Parse(this.tbHostPort.Text))//指定TCP连接的IP和Port
                             .WithCleanSession(false)//false 接收离线消息 服务端需要启用之久会话 WithPersistentSessions
                             .WithWillMessage(new MqttApplicationMessage { Topic = "ooo", Payload = Encoding.UTF8.GetBytes("下线通知"), Retain = true })
                             .WithWillDelayInterval(1)
                             .WithCredentials(this.tbUsername.Text, this.tbPassword.Text);//指定连接的用户名和密码

            var options = new ManagedMqttClientOptionsBuilder()
                        .WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
                        .WithClientOptions(mqttClientOptions.Build())
                        .Build();

            mqttClient.StartAsync(options);
        }

        private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            mqttClient?.StopAsync();
        }

        private async void btnSubscribe_Click(object sender, RoutedEventArgs e)
        {
            // 检查Topic是否为空
            var topic = this.tbTopic.Text;
            if (string.IsNullOrWhiteSpace(topic))
            {
                MessageBox.Show("订阅主题不能为空！");
                return;
            }

            // QoS  Quality of Service 服务质量
            // 发布与订阅的Qos不一致的情况：以Publish为主
            await mqttClient.SubscribeAsync(topic, MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce);
        }

        private async void btnUsubscribe_Click(object sender, RoutedEventArgs e)
        {
            // 检查Topic是否为空
            var topic = this.tbTopic.Text;
            if (string.IsNullOrWhiteSpace(topic))
            {
                MessageBox.Show("取消订阅主题不能为空！");
                return;
            }

            // 取消订阅
            await mqttClient.UnsubscribeAsync(topic);
        }

        private void btnPublish_Click(object sender, RoutedEventArgs e)
        {
            var topic = this.tbPubTopic.Text;
            var payload = this.tbContent.Text;

            // 检查一下相关数据的正确性
            if (string.IsNullOrWhiteSpace(topic))
            {
                MessageBox.Show("发布主题不能为空！");
                return;
            }

            mqttClient.PublishAsync(topic, payload, MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce);
        }
    }
}
